package no.rodland.acc.model;

import org.joda.time.DateTime;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import no.rodland.acc.db.AbstractRow;

/**
 * Created by IntelliJ IDEA.
 *
 * @Since: Jun 18, 2010 12:04:32 PM
 * @Author: fmr
 */
public class Bank extends AbstractRow {

    private DateTime interestDate;
    private DateTime accountDate;
    private DateTime useDate;
    private String ref;
    private BankType bankType;
    private String text;
    private int amountOut;
    private int amountIn;
    private int amount;
    private BankAccount bankAccount;
    private String budgeted;
    private String comment;

    public Bank(
            DateTime interestDate,
            DateTime accountDate,
            DateTime useDate,
            String ref,
            BankType bankType,
            String text,
            int amountOut,
            int amountIn,
            BankAccount bankAccount,
            String budgeted,
            String comment) {
        super(0, null, null);
        this.interestDate = interestDate;

        if (accountDate != null) {
            this.accountDate = accountDate;
        }
        else {
            this.accountDate = interestDate;
        }

        this.useDate = useDate != null ? useDate : (accountDate != null ? accountDate : interestDate);

        this.ref = ref;
        this.bankType = bankType;
        this.text = text;
        this.amountOut = amountOut;
        this.amountIn = amountIn;
        this.amount = getAmount();
        this.bankAccount = bankAccount;
        this.budgeted = budgeted;
        this.comment = comment;
    }

    protected Bank(ResultSet rs,
                   Map<Integer, BankType> bankTypes,
                   Map<Integer, BankAccount> bankAccounts) throws SQLException {
        super(rs.getInt("id"),
                new DateTime(rs.getTimestamp("updated_date")),
                new DateTime(rs.getTimestamp("created_date")));
        if (bankTypes != null) {
            bankType = bankTypes.get(rs.getInt("bank_type_id"));
        }
        if (bankAccounts != null) {
            bankAccount = bankAccounts.get(rs.getInt("bank_account_id"));
        }

        interestDate = new DateTime(rs.getDate("interest_date"));
        accountDate = new DateTime(rs.getDate("account_date"));
        final Date date = rs.getDate("use_date");
        useDate = date != null ? new DateTime(date) : (accountDate != null ? accountDate : interestDate);
        ref = rs.getString("ref");
        text = rs.getString("text");
        amountOut = rs.getInt("amount_out");
        amountIn = rs.getInt("amount_in");
        amount = rs.getInt("amount");
        budgeted = rs.getString("is_budgeted");
        comment = rs.getString("comment");
    }

    @Override
    public String getTableName() {
        return "bank";
    }

    @Override
    public Object[] getData() {
        return new Object[]{interestDate.toDate(), accountDate.toDate(), useDate.toDate(), ref, bankType.getId(), text, amountOut, amountIn, amount, bankAccount.getId(), budgeted, comment};
    }

    @Override
    public String[] getColumns() {
        return new String[]{"interest_date", "account_date", "use_date", "ref", "bank_type_id", "text", "amount_out", "amount_in", "amount", "bank_account_id", "is_budgeted", "comment"};
    }

    @Override
    public boolean usesIdentity() {
        return true;
    }

    public DateTime getInterestDate() {
        return interestDate;
    }

    public DateTime getAccountDate() {
        return accountDate;
    }

    public DateTime getUseDate() {
        return useDate;
    }

    public String getRef() {
        return ref;
    }

    public BankType getBankType() {
        return bankType;
    }

    public String getText() {
        return text;
    }

    public int getAmountOut() {
        return amountOut;
    }

    public int getAmountIn() {
        return amountIn;
    }

    public int getAmount() {
        return amountOut - amountIn;
    }

    public String getBudgeted() {
        return budgeted;
    }

    public String getComment() {
        return comment;
    }

    public BankAccount getBankAccount() {
        return bankAccount;
    }

    /**
     * Returns the date best describing this bank.
     */
    @Override
    public DateTime getDate() {
        return getUseDate();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Bank");
        sb.append("{interestDate=").append(interestDate);
        sb.append(", accountDate=").append(accountDate);
        sb.append(", useDate=").append(useDate);
        sb.append(", ref='").append(ref).append('\'');
        sb.append(", bankType.id=").append(bankType.getId());
        sb.append(", bankType.name=").append(bankType.getName());
        sb.append(", bankAccount.id=").append(bankAccount.getId());
        sb.append(", text='").append(text).append('\'');
        sb.append(", amountOut=").append(amountOut);
        sb.append(", amountIn=").append(amountIn);
        sb.append(", amount=").append(amount);
        sb.append(", budgeted=").append(budgeted);
        sb.append(", comment='").append(comment).append('\'');
        sb.append('}');
        return sb.toString();
    }

    @SuppressWarnings({"RedundantIfStatement"})
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Bank that = (Bank) o;
        if (getId() != 0 && that.getId() != 0 && that.getId() != getId()) {
            return false;
        }
        if (amount != that.amount) {
            return false;
        }
        if (amountIn != that.amountIn) {
            return false;
        }
        if (amountOut != that.amountOut) {
            return false;
        }
        if (accountDate != null ? !accountDate.equals(that.accountDate) : that.accountDate != null) {
            return false;
        }
        if (bankAccount != null ? !bankAccount.equals(that.bankAccount) : that.bankAccount != null) {
            return false;
        }
        if (bankType != null ? !bankType.equals(that.bankType) : that.bankType != null) {
            return false;
        }
        if (budgeted != null ? !budgeted.equals(that.budgeted) : that.budgeted != null) {
            return false;
        }
        if (comment != null ? !comment.equals(that.comment) : that.comment != null) {
            return false;
        }
        if (interestDate != null ? !interestDate.equals(that.interestDate) : that.interestDate != null) {
            return false;
        }
        if (ref != null ? !ref.equals(that.ref) : that.ref != null) {
            return false;
        }
        if (text != null ? !text.equals(that.text) : that.text != null) {
            return false;
        }
        if (useDate != null ? !useDate.equals(that.useDate) : that.useDate != null) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = interestDate != null ? interestDate.hashCode() : 0;
        result = 31 * result + (accountDate != null ? accountDate.hashCode() : 0);
        result = 31 * result + (useDate != null ? useDate.hashCode() : 0);
        result = 31 * result + (ref != null ? ref.hashCode() : 0);
        result = 31 * result + (bankType != null ? bankType.hashCode() : 0);
        result = 31 * result + (text != null ? text.hashCode() : 0);
        result = 31 * result + amountOut;
        result = 31 * result + amountIn;
        result = 31 * result + amount;
        result = 31 * result + (bankAccount != null ? bankAccount.hashCode() : 0);
        result = 31 * result + (budgeted != null ? budgeted.hashCode() : 0);
        result = 31 * result + (comment != null ? comment.hashCode() : 0);
        return result;
    }
}